package gsar.client;

import java.util.Collection;

/*
Copyright (c) 2009, Eric Eaton, University of Maryland Baltimore County
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the University of Maryland Baltimore County nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/** Describes a cell in the gridworld
 * 
 * @author Eric Eaton
 */
public class GWCell {

	/** The cell's coordinates */
	private GWCoordinate m_coordinates = null;
	
	/** A string representing the cell's marker */
	private String m_marker = null;
	
	/** A list of the walls around the cells, represented as a boolean vector
     *  in each of the cardinal directions ("north", "south", "east", "west")
     */
	private boolean[] m_walls = new boolean[GWDirection.numDirections()];
	
	/** The occupant of the cell */
	private GWObject m_occupant = null;

	/** Constructor for an unoccupied cell without a marker
	 * @param coordinates
	 * @param walls a list of the walls around the cells, e.g. ("north", "south", "east", "west")
	 */
	public GWCell(GWCoordinate coordinates, Collection<String> walls) {
		if (coordinates == null) {
			throw new IllegalArgumentException("coordinate cannot be null.");
		}
		
		m_coordinates = coordinates;
		
		if (walls != null) {
			for (String wall : walls) {
				m_walls[GWDirection.valueOf(wall).ordinal()] = true;
			}
		}
	}
	
	/** Constructor for an unoccupied cell with a marker
	 * @param coordinates
	 * @param walls a list of the walls around the cells, e.g. ("north", "south", "east", "west")
	 * @param marker the marker on this cell
	 */
	public GWCell(GWCoordinate coordinates, Collection<String> walls, String marker) {
		this(coordinates, walls);
		m_marker = marker;
	}
	
	/** Constructor for an occupied cell with a marker
	 * @param coordinates
	 * @param walls a list of the walls around the cells, e.g. ("north", "south", "east", "west")
	 * @param object the object located in this cell
	 * @param marker the marker on this cell
	 */
	public GWCell(GWCoordinate coordinates, Collection<String> walls, GWObject object, String marker) {
		this(coordinates, walls, marker);
		m_occupant = object;
	}
	
	/** Constructor for an occupied cell without a marker
	 * @param coordinates
	 * @param walls a list of the walls around the cells, e.g. ("north", "south", "east", "west")
	 * @param object the object located in this cell
	 */
	public GWCell(GWCoordinate coordinates, Collection<String> walls, GWObject object) {
		this(coordinates, walls);
		m_occupant = object;
	}
	
	/** Gets the coordinates of the cell
	 * @return the coordinates of the cell
	 */
	public GWCoordinate getCoordinates() { return m_coordinates; }
	
	/** Gets the cell's occupant, if any
	 * @return the cell's occupant, null if it is unoccupied
	 */
	public GWObject getOccupant() { return m_occupant; }
	
	/** Determines whether the cell has an occupant.
	 * @return whether the cell has an occupant
	 */
	public boolean hasOccupant() { return m_occupant != null; }
	
	/** Determines whether the cell has a marker
	 * @return whether the cell has a marker
	 */
	public boolean hasMarker() { return m_marker != null; }
	
	/** Gets the cell's marker, if any
	 * @return the cell's marker, null if it is unmarked
	 */
	public String getMarker() { return m_marker; }
	
	/** Determines whether the cell has a wall in the specified direction.
	 * @param direction the direction
	 * @return whether the cell has a wall in the given direction.
	 */
	public boolean hasWall(GWDirection direction) {
		return m_walls[direction.ordinal()];
	}
	
	/** Determines whether the cell has walls.
	 * @return whether the cell has walls
	 */
	public boolean hasWalls() {
		boolean hasWall = false;
		for (boolean b : m_walls) {
			if (b) {
				hasWall = true;
				break;
			}
		}
		return hasWall;
	}

	@Override
	public String toString() {
		String str = getCoordinates()+"[";
		for (GWDirection direction : GWDirection.values()) {
			if (hasWall(direction))
				str += direction.toString().substring(0, 1);
		}
		str += "]";
		if (m_marker != null)
			str += ":"+m_marker;
		return str;
	}

	
	public String toXML() {
		String s = "<cell> ";
		s += getCoordinates().toXML()+" ";
		if (hasMarker()) {
			s += "<marker>"+m_marker+"</marker> ";
		}
		
		if (hasWalls()) {
			for (GWDirection direction : GWDirection.values()) {
				if (hasWall(direction)) {
					s += "<wall>"+direction + "</wall> ";
				}
			}
		}
		
		if (hasOccupant()) {
			s += "<occupant>"+getOccupant()+"</occupant> ";
		}
		
		s += "</cell>";
		
		return s;
	}

}

